// -----------------------------------------------------------------------
//  <copyright file="CreateDictionaryItemCommand.cs" company="LiuliuSoft">
//      Copyright (c) 2025 66SOFT. All rights reserved.
//  </copyright>
//  <site>https://dapr.plus</site>
//  <last-editor>郭明锋</last-editor>
//  <last-date>2025-10-17 01:10</last-date>
// -----------------------------------------------------------------------

using DaprPlus.Authorization;
using DaprPlus.Domain;
using DaprPlus.DataDicts.Domain.Dtos;
using DaprPlus.DataDicts.Domain.Entities;
using DaprPlus.DataDicts.Domain.Specs;
using DaprPlus.Domain.Entity;
using DaprPlus.Mapping;
using DaprPlus.MediatR;

using FluentValidation;


namespace DaprPlus.DataDicts.Application.Commands;

[AuthConfig(typeof(DictionaryItem), ResourceAccessType.RoleLimit, "Create")]
public class CreateDictionaryItemCommand : IRequest<ApiResult>, ICommand
{
    public DictionaryItemInDto[] Dtos { get; set; } = [];
}

public class CreateDictionaryItemCommandHandler(IServiceProvider provider)
    : IRequestHandler<CreateDictionaryItemCommand, ApiResult>
{
    public async Task<ApiResult> Handle(CreateDictionaryItemCommand request, CancellationToken cancellationToken)
    {
        var logger = provider.GetLogger<CreateDictionaryItemCommandHandler>();
        var repository = provider.GetRepository<DictionaryType>();

        // 按字典类型分组处理
        var groupedDtos = request.Dtos.GroupBy(dto => dto.DictionaryTypeId);
        var createdItems = new List<DictionaryItem>();

        foreach (var group in groupedDtos)
        {
            var typeId = group.Key;
            var typeSpec = new DictionaryTypeByIdSpec(typeId).And(new DictionaryTypeWithItemsSpec());
            var dictionaryType = await repository.GetAsync(typeSpec, cancellationToken);

            if (dictionaryType == null)
            {
                logger.LogWarning("创建字典项时编号为 {TypeId} 的字典类型不存在", typeId);
                return new ApiResult(ApiResultType.Error, $"编号为 {typeId} 的字典类型不存在");
            }

            // 通过聚合根添加字典项，直接传递DTOs
            var result = dictionaryType.AddItem(group.ToArray());
            if (!result.IsSuccess())
            {
                logger.LogWarning("创建字典项失败：{Message}", result.Message);
                return result;
            }

            await repository.UpdateAsync(dictionaryType, cancellationToken);

            // 收集创建的字典项用于日志
            var createdEntities = dictionaryType.Items.Where(item =>
                group.Any(dto => dto.Label == item.Label && dto.Value == item.Value)).ToList();
            createdItems.AddRange(createdEntities);
        }

        logger.LogInformation("创建字典项【{Labels}】成功，数量：{Count}",
            createdItems.ExpandAndToString(m => m.Label), createdItems.Count);
        return new ApiResult(ApiResultType.Success, $"字典项 {createdItems.ExpandAndToString(m => m.Label)} 创建成功");
    }
}

public class CreateDictionaryItemCommandValidator : AbstractValidator<CreateDictionaryItemCommand>
{
    public CreateDictionaryItemCommandValidator(IQueryRepository<DictionaryItem> repository, IRepository<DictionaryType> typeRepository)
    {
        RuleFor(x => x.Dtos)
            .NotEmpty()
            .WithMessage("字典项数据不能为空")
            .Must(dtos =>
            {
                var values = dtos.Select(x => new { x.DictionaryTypeId, x.Value }).ToList();
                return values.Count == values.Distinct().Count();
            })
            .WithMessage("批量创建的字典项中存在重复的字典类型和值组合");

        RuleForEach(x => x.Dtos).ChildRules(dto =>
        {
            dto.RuleFor(x => x.Label)
                .NotEmpty()
                .MaximumLength(50)
                .WithMessage("字典项标签不能为空且长度不能超过50个字符");

            dto.RuleFor(x => x.Value)
                .NotEmpty()
                .MaximumLength(50)
                .WithMessage("字典项值不能为空且长度不能超过50个字符");

            dto.RuleFor(x => x.DictionaryTypeId)
                .MustAsync(async (typeId, cancellationToken) =>
                {
                    var spec = new DictionaryTypeByIdSpec(typeId);
                    var flag = await typeRepository.AnyAsync(spec, cancellationToken);
                    return flag;
                })
                .WithMessage(m => $"编号为 {m.DictionaryTypeId} 的字典类型不存在");

            dto.RuleFor(x => new { x.DictionaryTypeId, x.Value })
                .MustAsync(async (tuple, cancellationToken) =>
                {
                    var spec = new DictionaryItemByTypeIdAndValueSpec(tuple.DictionaryTypeId, tuple.Value);
                    var flag = await repository.AnyAsync(spec, cancellationToken);
                    return !flag;
                })
                .WithMessage(m => $"字典类型 {m.DictionaryTypeId} 下已存在值为 {m.Value} 的字典项");
        });
    }
}
